package cn.linlane.service;

import cn.linlane.entity.base.BaseEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.Assert;

import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * @author cheng
 * @date 2018-05-24 14:56
 */
public class BaseService<P extends BaseRepository<T, Long>, T extends BaseEntity> {

    @Autowired
    protected P repository;

    /** 修改 */
    public T update(T target) {
        Optional<T> source = repository.findById(target.getId());
        if (source.isPresent()) {
            BeanUtils.copyProperties(source.get(), target, getNoNullProperties(target));
        }
        return repository.save(target);
    }

    /** 新增 */
    public T save(T record) {
        return repository.save(record);
    }

    /** 删除 */
    public void delete(Long id) {
        Assert.notNull(id, "ID");
        Optional<T> optionalT = repository.findById(id);
        if (optionalT.isPresent()) {
            T t = optionalT.get();
            t.setDelete(true);
            repository.save(t);
        }
    }

    /**
     * 根据id查找
     * @param id
     * @return
     */
    public T queryById(Long id){
        Assert.notNull(id, "ID");
        Optional<T> optionalT = repository.findById(id);
        if (optionalT.isPresent()){
            return optionalT.get();
        } else {
            return null;
        }
    }

    /**
     * 分页查询所有结果
     * @param pageable
     * @return
     */
    public Page<T> findAll(Pageable pageable){
        return repository.findAll(pageable);
    }

    /**
     * 直接返回所有查询结果
     * @return
     */
    public List<T> findAll(){
        return repository.findAll();
    }

    /**
     * 根据实体类多条件查询
     * @param specification
     * @param pageable
     * @return
     */
    public Page<T> findAll(Specification<T> specification, Pageable pageable){
        return repository.findAll(specification, pageable);
    }

    /**
     * @param target 目标源数据
     * @return 将目标源中不为空的字段取出
     */
    private static String[] getNoNullProperties(Object target) {
        BeanWrapper srcBean = new BeanWrapperImpl(target);
        PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
        Set<String> noEmptyName = new HashSet<>();
        for (PropertyDescriptor p : pds) {
            Object value = srcBean.getPropertyValue(p.getName());
            if (value != null) {
                noEmptyName.add(p.getName());
            }
        }
        String[] result = new String[noEmptyName.size()];
        return noEmptyName.toArray(result);
    }

}

